package com.java.example.util.file

import android.content.ContentResolver
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Typeface
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.text.TextUtils
import android.webkit.MimeTypeMap
import android.widget.TextView
import com.java.example.app.Latte
import com.java.example.bean.EventType
import com.java.example.bean.MessageEvent
import org.greenrobot.eventbus.EventBus
import java.io.BufferedInputStream
import java.io.BufferedOutputStream
import java.io.BufferedReader
import java.io.ByteArrayOutputStream
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.net.HttpURLConnection
import java.net.URL
import java.text.SimpleDateFormat
import java.util.Collections
import java.util.Date
import java.util.Locale

object FileUtil {
    //格式化的模板
    private const val TIME_FORMAT = "_yyyyMMdd_HHmmss"

    private val SDCARD_DIR: String = Environment.getExternalStorageDirectory().path

    //默认本地上传图片目录
    val UPLOAD_PHOTO_DIR: String = Environment.getExternalStorageDirectory().path + "/a_upload_photos/"

    //网页缓存地址
    val WEB_CACHE_DIR: String = Environment.getExternalStorageDirectory().path + "/app_web_cache/"

    //内部存储
    val CAMERA_PHOTO_INTERNAL: String = Environment.getDataDirectory().path + "/Camera/"

    //系统相机目录
    val CAMERA_PHOTO_DIR: String = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path + "/Camera/"

    private fun getTimeFormatName(timeFormatHeader: String): String {
        val date = Date(System.currentTimeMillis())
        //必须要加上单引号
        val dateFormat = SimpleDateFormat("'" + timeFormatHeader + "'" + TIME_FORMAT, Locale.getDefault())
        return dateFormat.format(date)
    }

    /**
     * @param timeFormatHeader 格式化的头(除去时间部分)
     * @param extension        后缀名
     * @return 返回时间格式化后的文件名
     */
    fun getFileNameByTime(timeFormatHeader: String, extension: String): String {
        return getTimeFormatName(timeFormatHeader) + "." + extension
    }

    private fun createDir(sdcardDirName: String): File {
        //拼接成SD卡中完整的dir
        val dir = SDCARD_DIR + "/" + sdcardDirName + "/"
        val fileDir = File(dir)
        if (!fileDir.exists()) {
            fileDir.mkdirs()
        }
        return fileDir
    }

    fun createFile(sdcardDirName: String, fileName: String?): File {
        return File(createDir(sdcardDirName), fileName)
    }

    private fun createFileByTime(sdcardDirName: String, timeFormatHeader: String, extension: String): File {
        val fileName = getFileNameByTime(timeFormatHeader, extension)
        return createFile(sdcardDirName, fileName)
    }

    //获取文件的MIME
    fun getMimeType(filePath: String?): String? {
        val extension = getExtension(filePath)
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
    }

    //获取文件的后缀名
    @JvmStatic
    fun getExtension(filePath: String?): String {
        var suffix = ""
        val file = File(filePath)
        val name = file.name
        val idx = name.lastIndexOf('.')
        if (idx > 0) {
            suffix = name.substring(idx + 1)
        }
        return suffix
    }

    /**
     * 保存Bitmap到SD卡中
     *
     * @param dir      目录名,只需要写自己的相对目录名即可
     * @param compress 压缩比例 100是不压缩,值约小压缩率越高
     * @return 返回该文件
     */
    fun saveBitmap(mBitmap: Bitmap, dir: String, compress: Int): File? {
        val sdStatus = Environment.getExternalStorageState()
        // 检测sd是否可用
        if (sdStatus != Environment.MEDIA_MOUNTED) {
            return null
        }
        var fos: FileOutputStream? = null
        var bos: BufferedOutputStream? = null
        val fileName = createFileByTime(dir, "DOWN_LOAD", "jpg")
        try {
            fos = FileOutputStream(fileName)
            bos = BufferedOutputStream(fos)
            mBitmap.compress(Bitmap.CompressFormat.JPEG, compress, bos) // 把数据写入文件
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } finally {
            try {
                bos?.flush()
                bos?.close()
                //关闭流
                fos?.flush()
                fos?.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        refreshDCIM()

        return fileName
    }

    @JvmStatic
    fun writeToDisk(`is`: InputStream, dir: String, name: String?): File {
        val file = createFile(dir, name)
        var bis: BufferedInputStream? = null
        var fos: FileOutputStream? = null
        var bos: BufferedOutputStream? = null

        try {
            bis = BufferedInputStream(`is`)
            fos = FileOutputStream(file)
            bos = BufferedOutputStream(fos)

            val data = ByteArray(1024 * 4)

            var count: Int
            while ((bis.read(data).also { count = it }) != -1) {
                bos.write(data, 0, count)
            }

            bos.flush()
            fos.flush()
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                bos?.close()
                fos?.close()
                bis?.close()
                `is`.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }

        return file
    }

    @JvmStatic
    fun writeToDisk(`is`: InputStream, dir: String, prefix: String, extension: String): File {
        val file = createFileByTime(dir, prefix, extension)
        var bis: BufferedInputStream? = null
        var fos: FileOutputStream? = null
        var bos: BufferedOutputStream? = null

        try {
            bis = BufferedInputStream(`is`)
            fos = FileOutputStream(file)
            bos = BufferedOutputStream(fos)

            val data = ByteArray(1024 * 4)

            var count: Int
            while ((bis.read(data).also { count = it }) != -1) {
                bos.write(data, 0, count)
            }

            bos.flush()
            fos.flush()
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                bos?.close()
                fos?.close()
                bis?.close()
                `is`.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }

        return file
    }

    /**
     * 通知系统刷新系统相册，使照片展现出来
     */
    private fun refreshDCIM() {
        if (Build.VERSION.SDK_INT >= 19) {
            //兼容android4.4版本，只扫描存放照片的目录
            MediaScannerConnection.scanFile(
                    Latte.applicationContext,
                    arrayOf(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).path),
                    null, null
            )
        } else {
            //扫描整个SD卡来更新系统图库，当文件很多时用户体验不佳，且不适合4.4以上版本
            Latte.applicationContext.sendBroadcast(
                    Intent(
                            Intent.ACTION_MEDIA_MOUNTED, Uri.parse(
                            "file://" +
                                    Environment.getExternalStorageDirectory()
                    )
                    )
            )
        }
    }

    /**
     * 读取raw目录中的文件,并返回为字符串
     */
    @JvmStatic
    fun getRawFile(id: Int): String {
        val `is` = Latte.applicationContext.resources.openRawResource(id)
        val bis = BufferedInputStream(`is`)
        val isr = InputStreamReader(bis)
        val br = BufferedReader(isr)
        val stringBuilder = StringBuilder()
        var str: String?
        try {
            while ((br.readLine().also { str = it }) != null) {
                stringBuilder.append(str)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                br.close()
                isr.close()
                bis.close()
                `is`.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return stringBuilder.toString()
    }


    fun setIconFont(path: String?, textView: TextView) {
        val typeface = Typeface.createFromAsset(Latte.applicationContext.assets, path)
        textView.typeface = typeface
    }

    /**
     * 读取assets目录下的文件,并返回字符串
     */
    fun getAssetsFile(name: String?): String? {
        var `is`: InputStream? = null
        var bis: BufferedInputStream? = null
        var isr: InputStreamReader? = null
        var br: BufferedReader? = null
        var stringBuilder: StringBuilder? = null
        val assetManager = Latte.applicationContext.assets
        try {
            `is` = assetManager.open(name!!)
            bis = BufferedInputStream(`is`)
            isr = InputStreamReader(bis)
            br = BufferedReader(isr)
            stringBuilder = StringBuilder()
            var str: String?
            while ((br.readLine().also { str = it }) != null) {
                stringBuilder.append(str)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                br?.close()
                isr?.close()
                bis?.close()
                `is`?.close()
                assetManager.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
        return stringBuilder?.toString()
    }

    fun getRealFilePath(context: Context, uri: Uri?): String? {
        if (null == uri) return null
        val scheme = uri.scheme
        var data: String? = null
        if (scheme == null) data = uri.path
        else if (ContentResolver.SCHEME_FILE == scheme) {
            data = uri.path
        } else if (ContentResolver.SCHEME_CONTENT == scheme) {
            val cursor = context.contentResolver.query(uri, arrayOf(MediaStore.Images.ImageColumns.DATA), null, null, null)
            if (null != cursor) {
                if (cursor.moveToFirst()) {
                    val index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
                    if (index > -1) {
                        data = cursor.getString(index)
                    }
                }
                cursor.close()
            }
        }
        return data
    }

    fun downPdf(urlString: String) {
        try {
            val url = URL(urlString)
            val connection = url.openConnection() as HttpURLConnection
            connection.requestMethod = "GET"
            connection.doInput = true
            connection.doOutput = true
            connection.useCaches = false
            connection.connectTimeout = 5000
            connection.readTimeout = 5000
            //实现连接
            connection.connect()

            if (connection.responseCode == 200) {
                val `is` = connection.inputStream
                //以下为下载操作
                val arr = ByteArray(1)
                val baos = ByteArrayOutputStream()
                val bos = BufferedOutputStream(baos)
                var n = `is`.read(arr)
                while (n > 0) {
                    bos.write(arr)
                    n = `is`.read(arr)
                }
                bos.close()
                var path = Environment.getExternalStorageDirectory()
                    .toString() + "/download/"
                val name = urlString.split("/".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
                path = path + name[name.size - 1]
                val file = File(path)
                val fos = FileOutputStream(file)
                fos.write(baos.toByteArray())
                fos.close()
                //关闭网络连接
                connection.disconnect()
                if (null != file) {
                    EventBus.getDefault().post(MessageEvent(EventType.DOWN_FILE, file.absolutePath))
                }
                //                openPDF(file);//打开PDF文件
            }
        } catch (e: Exception) {
            // TODO: handle exception
            println(e.message)
        }
    }

    /**
     * 检查扩展名，得到图片格式的文件
     *
     * @param fName 文件名
     * @return
     */
    private fun checkIsImageFile(fName: String): Boolean {
        var isImageFile = false
        // 获取扩展名
        val FileEnd = fName.substring(
                fName.lastIndexOf(".") + 1,
                fName.length
        ).lowercase(Locale.getDefault())
        isImageFile = if (FileEnd == "jpg" || FileEnd == "png" || FileEnd == "gif" || FileEnd == "jpeg" || FileEnd == "bmp") {
            true
        } else {
            false
        }
        return isImageFile
    }


    /**
     * 对外接口  获取uri对应的路径
     *
     * @param uri
     * @return
     */
    fun getChooseFileResultPath(uri: Uri, context: Context): String? {
        var chooseFilePath: String? = null
        if ("file".equals(uri.scheme, ignoreCase = true)) { //使用第三方应用打开
            chooseFilePath = uri.path
            return chooseFilePath
        }
        chooseFilePath = if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { //4.4以后
            getRealFilePath(context, uri)
        } else { //4.4以下下系统调用方法
            getRealPathFromURI(uri, context)
        }
        return chooseFilePath
    }


    fun getRealPathFromURI(contentUri: Uri?, context: Context): String? {
        var res: String? = null
        val proj = arrayOf(MediaStore.Images.Media.DATA)
        val cursor = context.contentResolver.query(contentUri!!, proj, null, null, null)
        if (null != cursor && cursor.moveToFirst()) {
            val column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
            res = cursor.getString(column_index)
            cursor.close()
        }
        return res
    }
    fun copyFile(context: Context, dir: String?, fileName: String) {
        val rootPath = context.getExternalFilesDir(null)!!.absolutePath + if (TextUtils.isEmpty(dir)) "" else File.separator + dir
        val filePath = rootPath + File.separator + fileName
        if (File(filePath).exists()) {
            return
        }
        val rootFile = File(rootPath)
        if (!rootFile.exists()) {
            rootFile.mkdirs()
        }
        try {
            val open = context.assets.open(if (TextUtils.isEmpty(dir)) fileName else dir + File.separator + fileName)
            val fileOutputStream = FileOutputStream(filePath)
            val buffer = ByteArray(1024 * 8)
            var count = 0
            while (open.read(buffer).also { count = it } != -1) {
                fileOutputStream.write(buffer, 0, count)
            }
            open.close()
            fileOutputStream.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
